package com.xuecheng.content.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.zxing.common.StringUtils;
import com.huanf.domain.MqMessage;
import com.huanf.service.MqMessageService;
import com.xuecheng.base.enums.CourseEnum;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.content.config.MultipartSupportConfig;
import com.xuecheng.content.feignclient.MediaServiceClient;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.mapper.CourseMarketMapper;
import com.xuecheng.content.mapper.CoursePublishMapper;
import com.xuecheng.content.mapper.CoursePublishpreMapper;
import com.xuecheng.content.service.*;
import com.xuecheng.domain.dto.CourseBaseInfoDto;
import com.xuecheng.domain.dto.CoursePreviewDto;
import com.xuecheng.domain.dto.TeachPlanDto;
import com.xuecheng.domain.po.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;

/**
 * @author shiyi
 * 课程发布相关接口
 */
@Service
public class CoursePublishServiceImpl implements CoursePublishService {

    @Resource
    CourseBaseInfoService courseBaseInfoService;

    @Resource
    TeachPlanService teachPlanService;

    @Resource
    CourseMarketMapper courseMarketMapper;

    @Resource
    CoursePublishpreMapper coursePublishpreMapper;

    @Resource
    CourseBaseMapper courseBaseMapper;

    @Resource
    CoursePublishMapper coursePublishMapper;

    @Resource
    MqMessageService mqMessageService;

    @Resource
    CourseTeacherService courseTeacherService;

    @Resource
    MediaServiceClient mediaServiceClient;

    @Override
    public CoursePreviewDto getCoursePreviewInfo(Long courseId) {
        CoursePreviewDto coursePreviewInfo = new CoursePreviewDto();
        CourseBaseInfoDto courseBaseInfo = courseBaseInfoService.getCourseBaseInfo(courseId);
        List<TeachPlanDto> teachplanTree = teachPlanService.findTeachplanTree(courseId);
        coursePreviewInfo.setCourseBase(courseBaseInfo);
        coursePreviewInfo.setTeachplans(teachplanTree);
        return coursePreviewInfo;
    }

    @Override
    @Transactional
    public void commitAudit(Long companyId, Long courseId) {
        //如果课程的审核状态为已提交，则不允许再次提交

        //课程的图片，计划信息没有没有填写不允许提交


        //查询到课程基本信息，营销因袭，计划信息到课程预发布表中
        CourseBaseInfoDto courseBaseInfo = courseBaseInfoService.getCourseBaseInfo(courseId);
        if (courseBaseInfo == null){
            XueChengPlusException.cast("课程找不到");
        }
        CourseEnum auditStatus = courseBaseInfo.getAuditStatus();
        if (auditStatus.equals("202003")){
            XueChengPlusException.cast("课程已提交审核，请等待结果");
        }
        //本机构智能提交本机构的课程
        //todo
        String pic = courseBaseInfo.getPic();
        if (ObjectUtils.isEmpty(pic)) {
            XueChengPlusException.cast("请上传课程图片");
        }
        //查询课程计划
        List<TeachPlanDto> teachplanTree = teachPlanService.findTeachplanTree(courseId);
        if (teachplanTree == null || teachplanTree.isEmpty()) {
            XueChengPlusException.cast("请添加课程计划");
        }
        CoursePublishPre coursePublishPre = new CoursePublishPre();
        BeanUtils.copyProperties(courseBaseInfo, coursePublishPre);
        CourseMarket courseMarket = courseMarketMapper.selectById(courseId);
        String jsonString = JSON.toJSONString(courseMarket);
        coursePublishPre.setMarket(jsonString);
        String jsonString1 = JSON.toJSONString(teachplanTree);
        coursePublishPre.setTeachplan(jsonString1);
        //更新课程基本信息表的审核状态为已提交
        coursePublishPre.setStatus("202003");
        //提交时间
        coursePublishPre.setCreateDate(LocalDateTime.now());
        //查询预发布课程表，如果有则更新，没有则插入
        CoursePublishPre coursePublishPre1 = coursePublishpreMapper.selectById(courseId);
        if (coursePublishPre1 != null){
            coursePublishpreMapper.updateById(coursePublishPre);
        }else {
            //插入
            int insert = coursePublishpreMapper.insert(coursePublishPre);
        }
     //更新课程基本信息表的审核状态为已提交
        CourseBase courseBase = courseBaseMapper.selectById(courseId);
        courseBase.setAuditStatus(CourseEnum.AUDIT_STATUS_YES);
        courseBaseMapper.updateById(courseBase);
    }

    @Override
    @Transactional
    public void publish(Long companyId, Long courseId) {
        //查询预发布表向发布表写数据
        CoursePublishPre coursePublishPre = coursePublishpreMapper.selectById(courseId);
        if (coursePublishPre == null){
            XueChengPlusException.cast("课程预发布信息找不到");
        }
        //课程审核不通过，不允许发布
        String status = coursePublishPre.getStatus();
        if (!("202004").equals(status)){
            XueChengPlusException.cast("课程审核不通过，不允许发布");
        }
        CoursePublish coursePublish = new CoursePublish();
        BeanUtils.copyProperties(coursePublishPre, coursePublish);
        coursePublish.setCreateDate(null);
        CoursePublish coursePublishObj= coursePublishMapper.selectById(courseId);
        if (coursePublishObj == null){
           coursePublishMapper.insert(coursePublish);
        } else {
            coursePublishMapper.updateById(coursePublish);

        }
        //向消息表写入数据
        //todo
        MqMessage coursePublishMessage = mqMessageService.addMessage("course_publish", String.valueOf(courseId), null, null);
        if (coursePublishMessage == null){
            XueChengPlusException.cast("消息写入失败");
        }
        //将预发布表数据删除
        int i = coursePublishMapper.deleteById(courseId);
    }

    @Override
    public File generateCourseHtml(Long courseId) {
        Configuration configuration = new Configuration(Configuration.getVersion());
        //最终的静态文件
        File htmlFile = null;
        try {
            //拿到classpath路径
            String classpath = this.getClass().getResource("/").getPath();
            //指定模板目录
            configuration.setDirectoryForTemplateLoading(new File(classpath + "/templates/"));
            //指定编码
            configuration.setDefaultEncoding("utf-8");

            Template template = configuration.getTemplate("course_template.html");
            //准备数据
            CoursePreviewDto coursePreviewInfo = this.getCoursePreviewInfo(courseId);
            //获取任课老师
            LambdaQueryWrapper<CourseTeacher> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CourseTeacher::getCourseId,courseId);
            List<CourseTeacher> teacherList = courseTeacherService.list(wrapper);
            if (teacherList!=null) {
                coursePreviewInfo.setTeachers(teacherList);
            }
            HashMap<String, Object> map = new HashMap<>();
            map.put("model",coursePreviewInfo);

            //Template template 模板, Object model 数据
            String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
            //输入流
            InputStream inputStream = IOUtils.toInputStream(html, "utf-8");
            htmlFile = File.createTempFile("coursepublish",".html");
            //输出文件
            FileOutputStream outputStream = new FileOutputStream(htmlFile);
            //使用流将html写入文件
            IOUtils.copy(inputStream,outputStream);

        }  catch (Exception ex) {
            System.err.println("页面静态化出现问题,课程id: "+courseId);
            ex.printStackTrace();
        }
        return htmlFile;
    }

    @Override
    public void uploadCourseHtml(Long courseId, File file) {
        //将file转成multipartFile
        try {
            MultipartFile multipartFile = MultipartSupportConfig.getMultipartFile(file);
            //远程调用得到返回值
            String uploadedFile = mediaServiceClient.uploadFile(multipartFile, "course/" + courseId + ".html");
            if(uploadedFile==null){
                System.err.println("xue-content-service模块在远程调用xue-media-api模块时无响应或发生异常，已被熔断，课程id: "+courseId);
                XueChengPlusException.cast("上传静态文件过程中存在异常");
            }
        } catch (Exception e) {
            e.printStackTrace();
            XueChengPlusException.cast("上传静态文件过程中存在异常");
        }

    }
}
